using System;
using System.Linq;
using System.Data;
using System.Xml;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.Serialization;
using Widgetsphere.Core.DataAccess;
using Widgetsphere.Core.Util;
using Widgetsphere.Core.Logging;
using Widgetsphere.Core.Exceptions;
using ACME.Northwind.Business;
using ACME.Northwind.Business.Objects;
using ACME.Northwind.Business.Rules;
using ACME.Northwind.Business.SelectCommands;
using System.IO;
using System.Data.SqlClient;

namespace ACME.Northwind.Domain.Objects
{
	#region internal class
	/// <summary>
	/// This is an customizable extender for the domain class associated with the 'OrderDetail' object collection
	/// </summary>
	[Serializable()]
	[System.ComponentModel.DesignerCategoryAttribute("code")]
	partial class DomainOrderDetailCollection : PersistableDomainCollectionBase, IEnumerable, ISerializable, IDisposable
	{
		#region Member Variables

		//Generated Relationships This Object Plays Parent Role


		#endregion

		#region ISerializable Members
		/// <summary>
		/// Serialization constructor
		/// </summary>
		protected DomainOrderDetailCollection(SerializationInfo info, StreamingContext context):this()
		{

		}

		/// <summary>
		/// Method used internally for serialization
		/// </summary>
		public override void GetObjectData(SerializationInfo info, StreamingContext context)
		{

		}
		#endregion

		#region Properties

		internal SubDomain SubDomain
		{
			get{ return (SubDomain)this.DataSet; }
		}

		internal string Modifier
		{
			get{ return SubDomain.Modifier; }
		}

		internal virtual DataRelation OrderOrderDetailRelation
		{
			get
			{
				if(!this.SubDomain.Relations.Contains("OrderOrderDetailRelation"))
				{
					this.SubDomain.AddCollection(Collections.OrderCollection);
				}
				return this.SubDomain.Relations["OrderOrderDetailRelation"];
			}
		}

		internal virtual DataRelation ProductOrderDetailRelation
		{
			get
			{
				if(!this.SubDomain.Relations.Contains("ProductOrderDetailRelation"))
				{
					this.SubDomain.AddCollection(Collections.ProductCollection);
				}
				return this.SubDomain.Relations["ProductOrderDetailRelation"];
			}
		}

		//Generate Property Access To Related Tables
		internal virtual DomainOrderCollection RelatedOrderCollection
		{
			get { return (DomainOrderCollection)this.SubDomain.GetDomainCollection(Collections.OrderCollection); }
		}

		internal virtual DomainProductCollection RelatedProductCollection
		{
			get { return (DomainProductCollection)this.SubDomain.GetDomainCollection(Collections.ProductCollection); }
		}

		//Generated Domain Properties Where This Object Plays Both Roles

		#endregion

		#region Contructors /Initialization

		internal DomainOrderDetailCollection()
		{
			try
			{
				base.TableName = "OrderDetailCollection";
				this.InitClass();
			}
			catch (System.Data.DBConcurrencyException dbcex) { throw new ConcurrencyException(GlobalValues.ERROR_CONCURRENCY_FAILURE, dbcex); }
			catch (System.Data.SqlClient.SqlException sqlexp) { if (sqlexp.Number == 547 || sqlexp.Number == 2627) throw new UniqueConstraintViolatedException(GlobalValues.ERROR_CONSTRAINT_FAILURE, sqlexp); else throw; }
			catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.ToString()); throw; }
		}

		private void InitClass() 
		{
			BeginInit();
			this.columnUnitPrice = new DataColumn("UnitPrice", typeof(decimal), null, System.Data.MappingType.Element);
			base.Columns.Add(this.columnUnitPrice);
			this.columnUnitPrice.AllowDBNull = false;
			this.columnUnitPrice.DefaultValue = Decimal.MinValue;
			this.columnUnitPrice.Caption = "";
			this.columnQuantity = new DataColumn("Quantity", typeof(short), null, System.Data.MappingType.Element);
			base.Columns.Add(this.columnQuantity);
			this.columnQuantity.AllowDBNull = false;
			this.columnQuantity.DefaultValue = short.MinValue;
			this.columnQuantity.Caption = "";
			this.columnProductId = new DataColumn("ProductID", typeof(int), null, System.Data.MappingType.Element);
			base.Columns.Add(this.columnProductId);
			this.columnProductId.AllowDBNull = false;
			this.columnProductId.DefaultValue = int.MinValue;
			this.columnProductId.Caption = "";
			this.columnOrderId = new DataColumn("OrderID", typeof(int), null, System.Data.MappingType.Element);
			base.Columns.Add(this.columnOrderId);
			this.columnOrderId.AllowDBNull = false;
			this.columnOrderId.DefaultValue = int.MinValue;
			this.columnOrderId.Caption = "";
			this.columnDiscount = new DataColumn("Discount", typeof(System.Single), null, System.Data.MappingType.Element);
			base.Columns.Add(this.columnDiscount);
			this.columnDiscount.AllowDBNull = false;
			this.columnDiscount.DefaultValue = Single.MinValue;
			this.columnDiscount.Caption = "";
			this.columnModifiedBy = new DataColumn("ModifiedBy", typeof(string), null, System.Data.MappingType.Element);
			base.Columns.Add(this.columnModifiedBy);
			this.columnModifiedDate = new DataColumn("ModifiedDate", typeof(DateTime), null, System.Data.MappingType.Element);
			base.Columns.Add(this.columnModifiedDate);
			this.columnCreatedBy = new DataColumn("CreatedBy", typeof(string), null, System.Data.MappingType.Element);
			base.Columns.Add(this.columnCreatedBy);
			this.columnCreatedDate = new DataColumn("CreatedDate", typeof(DateTime), null, System.Data.MappingType.Element);
			base.Columns.Add(this.columnCreatedDate);
			this.columnTimeStamp = new DataColumn("TimeStamp", typeof(System.Byte[]), null, System.Data.MappingType.Element);
			base.Columns.Add(this.columnTimeStamp);
			base.Constraints.Add(new UniqueConstraint("PrimaryKey", new DataColumn[] {this.columnOrderId, this.columnProductId}, true));
			EndInit();
		}

		private bool mModifyUpdateOn = true;

		/// <summary>
		/// Raises the RowChanged event.
		/// </summary>
		protected override void OnRowChanged(DataRowChangeEventArgs e)
		{
			base.OnRowChanged(e);
			if(e.Action == DataRowAction.Change && mModifyUpdateOn)
			{
				mModifyUpdateOn = false;
				if ((e.Row[this.ModifiedByColumn] == System.DBNull.Value) || ((string)e.Row[this.ModifiedByColumn] != this.Modifier)) e.Row[this.ModifiedByColumn] = this.Modifier;
				mModifyUpdateOn = true;
			}
		}

		#endregion

		#region Database Retrieval

		internal DomainOrderDetail NewItem()
		{
			DomainOrderDetail retval = (DomainOrderDetail)(base.NewRow());
			((DataRow)retval)[ModifiedByColumn] = this.Modifier;
			((DataRow)retval)[ModifiedDateColumn] = DateTime.Now;
			((DataRow)retval)[CreatedByColumn] = this.Modifier;
			((DataRow)retval)[CreatedDateColumn] = DateTime.Now;
			((DataRow)retval)[DiscountColumn] = "0";
			((DataRow)retval)[QuantityColumn] = "1";
			((DataRow)retval)[UnitPriceColumn] = "0";

			return retval;
		}

		internal DomainOrderDetail NewItem(int orderid, int productid)
		{
			DomainOrderDetail retval = (DomainOrderDetail)(base.NewRow());
			((DataRow)retval)["OrderID"] = orderid;
			((DataRow)retval)["ProductID"] = productid;
			((DataRow)retval)[ModifiedByColumn] = this.Modifier;
			((DataRow)retval)[ModifiedDateColumn] = DateTime.Now;
			((DataRow)retval)[CreatedByColumn] = this.Modifier;
			((DataRow)retval)[CreatedDateColumn] = DateTime.Now;
			((DataRow)retval)[DiscountColumn] = "0";
			((DataRow)retval)[QuantityColumn] = "1";
			((DataRow)retval)[UnitPriceColumn] = "0";

			return retval;
		}

		internal void AddItem(DomainOrderDetail item)
		{
			base.Rows.Add(item);
		}

		internal void InsertAtOrderDetail(DomainOrderDetail item, int pos)
		{
			base.Rows.InsertAt(item, pos);
		}

		internal virtual void Persist()
		{
			this.SubDomain.Persist();
		}

		#region Select Methods

		internal static DomainOrderDetailCollection RunSelect(OrderDetailSearch search, string modifier)
		{
			SubDomain sd = new SubDomain(modifier);
			sd.AddSelectCommand(new OrderDetailSelectBySearch(search));
			sd.RunSelectCommands();
			return (DomainOrderDetailCollection)sd.GetDomainCollection(Collections.OrderDetailCollection);
		}

		internal static DomainOrderDetailCollection RunSelect(OrderDetailSearch search, OrderDetailPaging paging, string modifier)
		{
			SubDomain sd = new SubDomain(modifier);
			OrderDetailSelectBySearch command = new OrderDetailSelectBySearch(search, paging);
			sd.AddSelectCommand(command);
			sd.RunSelectCommands();
			paging.RecordCount = command.Count;
			return (DomainOrderDetailCollection)sd.GetDomainCollection(Collections.OrderDetailCollection);
		}

		internal static DomainOrderDetailCollection RunSelect(string modifier)
		{
			SubDomain sd = new SubDomain(modifier);
			sd.AddSelectCommand(new OrderDetailSelectAll());
			sd.RunSelectCommands();
			return (DomainOrderDetailCollection)sd.GetDomainCollection(Collections.OrderDetailCollection);
		}

		internal static DomainOrderDetailCollection RunSelect(int page, int pageSize, string orderByColumn, bool ascending, string filter, out int count, string modifier)
		{
			DomainOrderDetailCollection returnVal = null;
			SubDomain sd = new SubDomain(modifier);
			OrderDetailPagedSelect retrieveRule = new OrderDetailPagedSelect(page, pageSize, PersistableDomainCollectionBase.DataColumnNameToParameterName(orderByColumn), ascending, filter);
			sd.AddSelectCommand(retrieveRule);
			sd.RunSelectCommands();
			returnVal = (DomainOrderDetailCollection)sd.GetDomainCollection(Collections.OrderDetailCollection);
			count = retrieveRule.Count;
			return returnVal;
		}

		internal static DomainOrderDetailCollection SelectByOrderDetailPks(List<OrderDetailPrimaryKey> primaryKeys, string modifier)
		{
			SubDomain sd = new SubDomain(modifier);
			sd.AddSelectCommand(new OrderDetailSelectByPks(primaryKeys));
			sd.RunSelectCommands();
			return (DomainOrderDetailCollection)sd.GetDomainCollection(Collections.OrderDetailCollection);
		}

		#endregion

		#endregion

		#region DomainOrderDetail Collection Methods
		internal void RemoveOrderDetail(DomainOrderDetail item) 
		{
			base.Rows.Remove(item);
		}

		internal virtual int Count 
		{
			get { return base.Rows.Count; }
		}

		/// <summary>
		/// Returns an enumerator that can be used to iterate through the collection.
		/// </summary>
		/// <returns>An Enumerator that can iterate through the objects in this collection.</returns>
		public virtual System.Collections.IEnumerator GetEnumerator() 
		{
			return base.Rows.GetEnumerator();
		}

		/// <summary>
		/// Gets or sets the element at the specified index.
		/// </summary>
		/// <param name="index">The zero-based index of the element to get or set. </param>
		/// <returns>The element at the specified index.</returns>
		internal DomainOrderDetail this[int index] 
		{
			get { return ((DomainOrderDetail)(base.Rows[index])); }
		}

		internal DomainOrderDetail GetOrderDetail(int orderid, int productid)
		{
			return ((DomainOrderDetail)(base.Rows.Find(new object[] {orderid, productid})));
		}

		#endregion

		#region Data Columns Setup
		protected DataColumn columnUnitPrice;
		protected DataColumn columnQuantity;
		protected DataColumn columnProductId;
		protected DataColumn columnOrderId;
		protected DataColumn columnDiscount;
		protected DataColumn columnCreatedBy;
		protected DataColumn columnCreatedDate;
		protected DataColumn columnModifiedBy;
		protected DataColumn columnModifiedDate;
		protected DataColumn columnTimeStamp;
		[Widgetsphere.Core.Attributes.DataSetting("", false, 0)]
		public DataColumn UnitPriceColumn 
		{
			get { return this.columnUnitPrice; }
		}

		[Widgetsphere.Core.Attributes.DataSetting("", false, 0)]
		public DataColumn QuantityColumn 
		{
			get { return this.columnQuantity; }
		}

		[Widgetsphere.Core.Attributes.DataSetting("", false, 0)]
		public DataColumn ProductIdColumn 
		{
			get { return this.columnProductId; }
		}

		[Widgetsphere.Core.Attributes.DataSetting("", false, 0)]
		public DataColumn OrderIdColumn 
		{
			get { return this.columnOrderId; }
		}

		[Widgetsphere.Core.Attributes.DataSetting("", false, 0)]
		public DataColumn DiscountColumn 
		{
			get { return this.columnDiscount; }
		}

		[Widgetsphere.Core.Attributes.DataSetting(false)]
		public DataColumn ModifiedDateColumn 
		{
			get { return this.columnModifiedDate; }
		}

		[Widgetsphere.Core.Attributes.DataSetting(false)]
		public DataColumn ModifiedByColumn 
		{
			get { return this.columnModifiedBy; }
		}

		[Widgetsphere.Core.Attributes.DataSetting(false)]
		public DataColumn CreatedDateColumn 
		{
			get { return this.columnCreatedDate; }
		}

		[Widgetsphere.Core.Attributes.DataSetting(false)]
		public DataColumn CreatedByColumn 
		{
			get { return this.columnCreatedBy; }
		}

		[Widgetsphere.Core.Attributes.DataSetting(false)]
		public DataColumn TimeStampColumn 
		{
			get { return this.columnTimeStamp; }
		}

		#endregion

		#region Protected Overrides

		/// <summary>
		/// Create a new instance of this object type
		/// </summary>
		protected override DataTable CreateInstance()
		{
			return new DomainOrderDetailCollection();
		}

		/// <summary>
		/// Create new row from a DataRowBuilder
		/// </summary>
		/// <param name="builder">The DataRowBuilder object that is used to create the new row</param>
		/// <returns>A new datarow of type 'OrderDetail'</returns>
		protected override DataRow NewRowFromBuilder(DataRowBuilder builder)
		{
			DomainOrderDetail retval = new DomainOrderDetail(builder);
			return retval;
		}

		/// <summary>
		/// Returns the type of the datarow that this collection holds
		/// </summary>
		protected override System.Type GetRowType() 
		{
			return typeof(DomainOrderDetail);
		}
		#endregion

		#region Implement Persistable Table Abstact Methods

		/// <summary>
		/// Gets a list of parameters for SQL update commands.
		/// </summary>
		protected override List<IDbDataParameter> GetUpdateFreeSqlParameters()
		{
			return null;
		}

		/// <summary>
		/// Gets a list of parameters for SQL insert commands.
		/// </summary>
		protected override List<IDbDataParameter> GetInsertFreeSqlParameters()
		{
			return null;
		}

		/// <summary>
		/// Gets a list of parameters for SQL delete commands.
		/// </summary>
		protected override List<IDbDataParameter> GetDeleteFreeSqlParameters()
		{
			return null;
		}

		/// <summary>
		/// Determines if the stored procedure or SQL text is used for CRUD operations.
		/// </summary>
		protected override bool UseStoredProcedure
		{
			get { return true; }
		}

		/// <summary>
		/// The stored procedure name that performs deletes for the objects in this collection
		/// </summary>
		protected override string DeleteStoredProcedureName
		{
			get { return "gen_OrderDetailDelete"; }
		}

		/// <summary>
		/// The SQL that performs deletes for the objects in this collection
		/// </summary>
		protected override string DeleteSQLText
		{
			get { return null; }
		}

		/// <summary>
		/// The stored procedure name that performs inserts for the objects in this collection
		/// </summary>
		protected override string InsertStoredProcedureName
		{
			get { return "gen_OrderDetailInsert"; }
		}

		/// <summary>
		/// The SQL that performs inserts for the objects in this collection
		/// </summary>
		protected override string InsertSQLText
		{
			get { return null; }
		}

		/// <summary>
		/// The stored procedure name that performs updates for the objects in this collection
		/// </summary>
		protected override string UpdateStoredProcedureName
		{
			get { return "gen_OrderDetailUpdate"; }
		}

		/// <summary>
		/// The SQL that performs updates for the objects in this collection
		/// </summary>
		protected override string UpdateSQLText
		{
			get { return null; }
		}

		public override void SetChildSelectedFalse()
		{
		}

		/// <summary>
		/// Creates the referential integrity for this collection
		/// </summary>
		public override void CreateRelations()
		{
		}

		bool _handlingError = false;
		/// <summary>
		/// Determines if errors are handled by this object
		/// </summary>
		public override bool HandleErrors()
		{
			if (_handlingError) return false;
			_handlingError = true;
			try
			{
			DataRow[] rowsInError = this.GetErrors();
			List<OrderPrimaryKey> OrderPrimaryKeys = new List<OrderPrimaryKey>();
			List<ProductPrimaryKey> ProductPrimaryKeys = new List<ProductPrimaryKey>();

			foreach(DomainOrderDetail item in rowsInError)
			{
				item.ClearErrors();
				if((item.ParentCol.SubDomain.Contains(ACME.Northwind.Business.Collections.OrderCollection)) &&
					item.OrderItem == null)
				{
					OrderPrimaryKey newKey = new OrderPrimaryKey(item.OrderId);
					if (!OrderPrimaryKeys.Contains(newKey)) OrderPrimaryKeys.Add(newKey);
				}
				if((item.ParentCol.SubDomain.Contains(ACME.Northwind.Business.Collections.ProductCollection)) &&
					item.ProductItem == null)
				{
					ProductPrimaryKey newKey = new ProductPrimaryKey(item.ProductId);
					if (!ProductPrimaryKeys.Contains(newKey)) ProductPrimaryKeys.Add(newKey);
				}
			}
			bool handledError = false;

			if(OrderPrimaryKeys.Count > 0)
			{
				OrderSelectByPks retrieve = new OrderSelectByPks(OrderPrimaryKeys);
				this.SubDomain.AddSelectCommand(retrieve);
				handledError = true;
			}

			if(ProductPrimaryKeys.Count > 0)
			{
				ProductSelectByPks retrieve = new ProductSelectByPks(ProductPrimaryKeys);
				this.SubDomain.AddSelectCommand(retrieve);
				handledError = true;
			}

			return handledError;
			}
			catch
			{
				throw;
			}
			finally
			{
				_handlingError = false;
			}
		}
		#endregion 

		#region Helper Methods

		internal virtual string GetPrimaryKeyXml()
		{
			return GetPrimaryKeyXml(((IEnumerable<ACME.Northwind.Business.Objects.OrderDetail>)new ACME.Northwind.Business.Objects.OrderDetailCollection(this)).Select(x => x.PrimaryKey));
		}

		internal static string GetPrimaryKeyXml(ACME.Northwind.Business.Objects.OrderDetailPrimaryKey primaryKey)
		{
			List<ACME.Northwind.Business.Objects.OrderDetailPrimaryKey> list = new List<ACME.Northwind.Business.Objects.OrderDetailPrimaryKey>();
			list.Add(primaryKey);
			return GetPrimaryKeyXml(new List<ACME.Northwind.Business.Objects.OrderDetailPrimaryKey>(list));
		}

		internal static string GetPrimaryKeyXml(IEnumerable<ACME.Northwind.Business.Objects.OrderDetailPrimaryKey> primaryList)
		{
			StringWriter sWriter = new StringWriter();
			XmlTextWriter xWriter = new XmlTextWriter(sWriter);
			xWriter.WriteStartDocument();
			xWriter.WriteStartElement("Order_DetailsList");
			foreach(ACME.Northwind.Business.Objects.OrderDetailPrimaryKey primaryKey in primaryList)
			{
				xWriter.WriteStartElement("Order_Details");
				xWriter.WriteStartElement("OrderID");
				xWriter.WriteString(primaryKey.OrderId.ToString());
				xWriter.WriteEndElement();
				xWriter.WriteStartElement("ProductID");
				xWriter.WriteString(primaryKey.ProductId.ToString());
				xWriter.WriteEndElement();
				xWriter.WriteEndElement();
			}
			xWriter.WriteEndElement();
			xWriter.WriteEndDocument();
			xWriter.Flush();
			xWriter.Close();
			return sWriter.ToString();
		}


		private string GetOrderForeignKeyXml()
		{
			StringWriter sWriter = new StringWriter();
			XmlTextWriter xWriter = new XmlTextWriter(sWriter);
			xWriter.WriteStartDocument();
			xWriter.WriteStartElement("OrdersList");
			foreach(DomainOrderDetail orderdetail in this)
			{
				xWriter.WriteStartElement("Orders");
					xWriter.WriteStartElement("OrderID");
					xWriter.WriteString(orderdetail.OrderId.ToString());
					xWriter.WriteEndElement();
				xWriter.WriteEndElement();
			}
			xWriter.WriteEndElement();
			xWriter.WriteEndDocument();
			xWriter.Flush();
			xWriter.Close();
			return sWriter.ToString();
		}


		private string GetProductForeignKeyXml()
		{
			StringWriter sWriter = new StringWriter();
			XmlTextWriter xWriter = new XmlTextWriter(sWriter);
			xWriter.WriteStartDocument();
			xWriter.WriteStartElement("ProductsList");
			foreach(DomainOrderDetail orderdetail in this)
			{
				xWriter.WriteStartElement("Products");
					xWriter.WriteStartElement("ProductID");
					xWriter.WriteString(orderdetail.ProductId.ToString());
					xWriter.WriteEndElement();
				xWriter.WriteEndElement();
			}
			xWriter.WriteEndElement();
			xWriter.WriteEndDocument();
			xWriter.Flush();
			xWriter.Close();
			return sWriter.ToString();
		}

		#endregion

		#region Methods

		#endregion

		#region IDisposable Members

		void IDisposable.Dispose()
		{
		}

		#endregion

	}
	#endregion

}
